﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Noebe;
using Pixysoft.Framework.Security.Tokens;
using System.Data;
using Pixysoft.Framework.XSchEmA.Entity;
using Pixysoft.IO;
using Pixysoft.Framework.XSchEmA;

namespace Pixysoft.Framework.Security
{
    public class TokenSecurityManager
    {
        Pixysoft.Cache.ObjectCache<TokenCacheProfile> tokencache =
            new Pixysoft.Cache.ObjectCache<TokenCacheProfile>(); //token 缓存

        private static volatile TokenSecurityManager instance;

        private static object syncRoot = new Object();

        public static TokenSecurityManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new TokenSecurityManager();
                    }
                }

                return instance;

            }
        }




        public ITokenAccessDesigner AccessDesigner
        {
            get
            {
                return TokenAccessController.Instance;
            }
        }

        public ITokenUserInfoDesigner UserInfoDesigner
        {
            get
            {
                return TokenUserInfoController.Instance;
            }
        }

        /// <summary>
        /// 注册一个有效用户
        /// </summary>
        /// <returns></returns>
        public bool Register(string token, string username, string md5password)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            if (string.IsNullOrEmpty(username))
                return false;

            if (string.IsNullOrEmpty(md5password))
                return false;

            username = username.Trim().ToUpper();


            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            if (!TokenController.Instance.TokenValidate(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            return TokenUserInfoController.Instance.Register(username, md5password);
        }

        /// <summary>
        /// 用户登录获取信息 使用相同的帐号可以重复获得token，而且都有效
        /// </summary>
        /// <returns></returns>
        public string Login(string username, string md5password)
        {
            return Login(username, md5password, TokenHelper.default_tokendb_TimeOut);
        }
        /// <summary>
        /// 添加了超时设定 使用相同的帐号可以重复获得token，而且都有效
        /// </summary>
        /// <param name="username"></param>
        /// <param name="md5password"></param>
        /// <returns></returns>
        public string Login(string username, string md5password, int timeoutMins)
        {
            if (string.IsNullOrEmpty(username))
                return null;

            if (string.IsNullOrEmpty(md5password))
                return null;

            username = username.Trim().ToUpper();

            DataRow row = TokenUserInfoController.Instance.GetProfile(username, md5password);

            if (row == null)
                return null;

            string usercode = row["USERCODE"].ToString();

            string token = TokenController.Instance.Login(row, timeoutMins);

            if (string.IsNullOrEmpty(token))
                return token;

            //add to cache

            TokenCacheProfile profile = new TokenCacheProfile(token, usercode);

            profile.IsSuperUser = bool.Parse(row["ISSUPERUSER"].ToString());

            foreach (string accessname in TokenAccessController.Instance.GetAccessList(usercode))
            {
                profile.AccessList.Add(accessname);
            }

            if (!tokencache.Contains(token))
                tokencache.Add(token, profile, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));

            return token;
        }

        /// <summary>
        /// 清空所有的tokens
        /// </summary>
        /// <param name="username"></param>
        /// <param name="md5password"></param>
        /// <returns></returns>
        public void TokensPurge(string username, string md5password)
        {
            if (string.IsNullOrEmpty(username))
                return;

            if (string.IsNullOrEmpty(md5password))
                return;

            username = username.Trim().ToUpper();

            DataRow usrrow = TokenUserInfoController.Instance.GetProfile(username, md5password);

            if (usrrow == null)
                return;

            TokenController.Instance.ShutDown();

            tokencache.Clear();
        }

        /// <summary>
        /// 用户登出 同时删除其他过期的token
        /// </summary>
        /// <returns></returns>
        public void Logout(string token)
        {
            if (string.IsNullOrEmpty(token))
                return;

            TokenController.Instance.TokenRemove(token);

            TokenController.Instance.TokenExpiredRemove();

            tokencache.Remove(token);
        }

        /// <summary>
        /// 允许匿名访问
        /// </summary>
        /// <returns></returns>
        public string AnonymousLogin()
        {
            string token = TokenController.Instance.AnonymousLogin();

            TokenCacheProfile profile = new TokenCacheProfile(token, null);

            //匿名登录不使用缓存

            //if (!tokencache.Contains(token))
            //{
            //    tokencache.Add(token, profile, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));
            //}

            return token;
        }

        /// <summary>
        /// 帐户注销
        /// </summary>
        /// <param name="token"></param>
        /// <param name="username"></param>
        /// <param name="md5password"></param>
        /// <returns></returns>
        public bool Cancellation(string token, string username, string md5password)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            if (string.IsNullOrEmpty(username))
                return false;

            if (string.IsNullOrEmpty(md5password))
                return false;

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            if (!TokenController.Instance.TokenValidate(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            //09-11-08 bug

            username = username.Trim().ToUpper();

            return TokenUserInfoController.Instance.Cancellation(username, md5password);
        }

        /// <summary>
        /// 关闭token系统
        /// </summary>
        public bool ShutDown(string token)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            if (!TokenController.Instance.TokenValidate(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            TokenController.Instance.ShutDown();

            TokenUserInfoController.Instance.ShutDown();

            TokenAccessController.Instance.ShutDown();

            tokencache.Clear();

            return true;
        }

        /// <summary>
        /// 重启服务器 获取默认帐号 只有当用户列表空的时候才生效
        /// </summary>
        public bool Restart()
        {
            if (TokenUserInfoController.Instance.HasProfile())
                return false;

            TokenUserInfoController.Instance.Restart();

            return true;
        }

        /// <summary>
        /// 重新加载用户列表 必须使用已经登录帐户操作
        /// </summary>
        public bool Reload(string token)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(token);

                return false;
            }

            if (!TokenController.Instance.TokenValidate(row))
            {
                return false;
            }

            TokenUserInfoController.Instance.Reload();

            return true;
        }

        /// <summary>
        /// 验证token是否有效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool TokenValidate(string token)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            if (tokencache.Contains(token))
            {
                LoggerHelper.Debug("verify from token cache.");

                return true;
            }

            LoggerHelper.Debug("verify from database token.");

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return true;
            }

            if (TokenController.Instance.TokenValidate(row))
            {
                string usercode = row["USERCODE"].ToString();

                TokenCacheProfile profile = new TokenCacheProfile(token, usercode);

                profile.IsSuperUser = bool.Parse(row["ISSUPERUSER"].ToString());

                foreach (string accessname in TokenAccessController.Instance.GetAccessList(usercode))
                {
                    profile.AccessList.Add(accessname);
                }

                tokencache.Add(token, profile, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));

                return true;
            }

            return false;
        }

        /// <summary>
        /// 验证token是否有效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool TokenValidate(string token, string accessname)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            if (string.IsNullOrEmpty(accessname))
                return false;

            accessname = accessname.Trim().ToUpper();

            if (tokencache.Contains(token))
            {
                TokenCacheProfile profile = tokencache.Get(token);

                if (profile.IsSuperUser)
                    return true;

                return profile.AccessList.Contains(accessname);

                return true;
            }

            LoggerHelper.Debug("verify from database token.");

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return true;
            }

            if (TokenController.Instance.TokenValidate(row))
            {
                string usercode = row["USERCODE"].ToString();

                TokenCacheProfile profile = new TokenCacheProfile(token, usercode);

                profile.IsSuperUser = bool.Parse(row["ISSUPERUSER"].ToString());

                foreach (string naccessname in TokenAccessController.Instance.GetAccessList(usercode))
                {
                    profile.AccessList.Add(naccessname);
                }

                tokencache.Add(token, profile, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));

                if (profile.IsSuperUser)
                    return true;

                return profile.AccessList.Contains(accessname);
            }

            return false;
        }

        /// <summary>
        /// token延长有效期 
        /// 如果是匿名token 直接删除返回false 
        /// 如果是失效token，删除返回false
        /// 否则就延期
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool TokenExtend(string token)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            if (tokencache.Contains(token))
            {
                tokencache.Extend(token, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));

                return true;
            }

            DataRow row = TokenController.Instance.GetTokenRow(token);

            if (row == null)
                return false;

            if (TokenController.Instance.IsAnonymous(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            if (!TokenController.Instance.TokenValidate(row))
            {
                TokenController.Instance.TokenRemove(row);

                return false;
            }

            if (TokenController.Instance.TokenExtend(row))
            {
                string usercode = row["USERCODE"].ToString();

                TokenCacheProfile profile = new TokenCacheProfile(token, usercode);

                profile.IsSuperUser = bool.Parse(row["ISSUPERUSER"].ToString());

                foreach (string accessname in TokenAccessController.Instance.GetAccessList(usercode))
                {
                    profile.AccessList.Add(accessname);
                }

                tokencache.Add(token, profile, TokenHelper.DateTimeNow.AddSeconds(TokenHelper.default_tokencache_Timeout));

                return true;
            }

            return false;
        }


        /// <summary>
        /// 判断是否匿名
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool IsAnonymous(string token)
        {
            if (string.IsNullOrEmpty(token))
                return false;

            return TokenController.Instance.IsAnonymous(token);
        }


        /// <summary>
        /// 是否在白名单
        /// </summary>
        /// <param name="ipaddress"></param>
        /// <returns></returns>
        public bool IsWhitelist(string ipaddress)
        {
            return false;
        }

        /// <summary>
        /// 是否在黑名单
        /// </summary>
        /// <param name="ipaddress"></param>
        /// <returns></returns>
        public bool IsBlacklist(string ipaddress)
        {
            return false;
        }
    }
}
